package com.time.store.auth.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.time.store.auth.entity.bo.Modules;
import com.time.store.auth.entity.bo.RoleModules;
import com.time.store.auth.entity.dto.ModulesPageQueryReq;
import com.time.store.auth.entity.dto.UpdateModuleByRoleReq;
import com.time.store.auth.entity.vo.ModulesListRes;
import com.time.store.auth.logic.IntegerOrder;
import com.time.store.auth.mapper.ModulesMapper;
import com.time.store.core.util.AuthUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

/**
 * <p>
 * 模块表 服务实现类
 * </p>
 *
 * @author 时间
 * @since 2021-04-25
 */
@Service
public class ModulesService extends ServiceImpl<ModulesMapper, Modules> implements IService<Modules> {
    @Autowired
    private RolesService rolesService;
    @Autowired
    private RoleModulesService roleModulesService;

    /**
     * @return
     */
    public List<Tree<Integer>> getModulesByUserId(Integer userId) {
        List<Integer> roleIds = rolesService.getByUserId(userId);
        if (CollUtil.isEmpty(roleIds)) {
            return new ArrayList<>();
        }
        List<Integer> moduleIds = roleModulesService
                .lambdaQuery()
                .in(RoleModules::getRoleId, roleIds)
                .list()
                .stream()
                .map(RoleModules::getModuleId)
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(moduleIds)) {
            return new ArrayList<>();
        }
        List<Modules> modules = lambdaQuery().in(Modules::getId, moduleIds).list();
        return listModuleToTree(modules);
    }


    /**
     * 分页查询菜单
     *
     * @param modulesPageQueryReq
     * @return
     */
    public List<Tree<Integer>> listModule(ModulesPageQueryReq modulesPageQueryReq) {
        List<Modules> modules = baseMapper.listModule(modulesPageQueryReq);
        return listModuleToTree(modules);
    }


    /**
     * 根据角色id查询菜单
     *
     * @param roleId
     * @return
     */
    public List<Tree<Integer>> listByRole(Integer roleId) {
        List<ModulesListRes> modulesListResList = baseMapper.listByRole(roleId);
        return listModuleToTree(modulesListResList, (treeNode, tree) -> {
            ModulesListRes modulesListRes = (ModulesListRes) treeNode;
            tree.putExtra("check", modulesListRes.isCheck());
        });
    }

    /**
     * 修改菜单根据角色
     *
     * @param updateModuleByRoleReq
     */
    public void updateModuleByRole(UpdateModuleByRoleReq updateModuleByRoleReq) {
        // 删除之前角色配置菜单
        QueryWrapper<RoleModules> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", updateModuleByRoleReq.getRoleId());
        queryWrapper.eq("store_id", AuthUtil.getCurrStoreId());
        roleModulesService.remove(queryWrapper);
        List<RoleModules> roleModulesList = updateModuleByRoleReq.getModules().stream().map(item -> {
            RoleModules roleModules = new RoleModules();
            roleModules.setStoreId(AuthUtil.getCurrStoreId());
            roleModules.setRoleId(updateModuleByRoleReq.getRoleId());
            roleModules.setModuleId(item);
            return roleModules;
        }).collect(Collectors.toList());
        roleModulesService.saveBatch(roleModulesList);
    }

    private List<Tree<Integer>> listModuleToTree(List<? extends Modules> modules) {
        return listModuleToTree(modules, null);
    }

    private List<Tree<Integer>> listModuleToTree(List<? extends Modules> modules, BiConsumer<Modules, Tree> treeBigConsumer) {

        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 最大递归深度
        treeNodeConfig.setDeep(3);

        List<Tree<Integer>> treeNodes = TreeUtil.build(modules, 0, treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId());

                    tree.setParentId(treeNode.getParentId());
                    tree.setWeight(new IntegerOrder(treeNode.getWeight()));

                    tree.setName(treeNode.getName());
                    // 扩展属性 ...
                    tree.putExtra("path", treeNode.getPath());
                    tree.putExtra("code", treeNode.getCode());
                    tree.putExtra("iconClass", treeNode.getIconClass());
                    tree.putExtra("createTime", treeNode.getCreateTime());
                    tree.putExtra("updateTime", treeNode.getUpdateTime());
                    if (treeBigConsumer != null)
                        treeBigConsumer.accept(treeNode, tree);
                });
        return treeNodes;
    }

}
